import java.awt.Component;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.URL;

import javax.swing.JFileChooser;

import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;
import org.jdom.output.Format;
import org.jdom.output.XMLOutputter;
import org.jdom.transform.XSLTransformException;
import org.jdom.transform.XSLTransformer;

/**
 * @author xhagesta
 * This class manages all tasks related to config file and user data import/export
 */
public class configFile {
	  
	public String ipAddress = null;
	public String adminUsername = null;;
	public String adminPassword = null;
	public String remoteNetwork = null;
	public String lowIp = null;
	public String highIp = null;
	public String dnsIp = null;
	public Boolean preferencesLoaded;
	private String prefFile = ".srxdynamicvpnmanager";
	private File usersFile;
	private Element root;
	private Document doc;
	private XMLOutputter xmlPrint;
	private JFileChooser jFc = new JFileChooser();
	private Component parent;
	private basicCrypto bc = null;
	private XSLTransformer xlsPrivate = null;

	/**
	 * Class constructor
	 * @param parent	Parent is the Constructor ancestor where error modal dialogs will be bound to
	 */
	public configFile(Component parent) {
		root = new Element("srxDynVpnManager");
		doc = new Document(root);
		try {
			xlsPrivate = new XSLTransformer(this.getClass().getResourceAsStream("resource/onlyCPassword.xsl"));
		} catch (XSLTransformException e) {
			// There is no need to manage this exception as we're providing the resource in the jar package
			e.printStackTrace();
		}
		root.addContent (new Element("ipAddress"));
		root.addContent (new Element("adminUsername"));
		root.addContent (new Element("adminPassowrd"));
		root.addContent (new Element("remoteNetwork"));
		root.addContent (new Element("lowIp"));
		root.addContent (new Element("highIp"));
		root.addContent (new Element("dnsIp"));
		xmlPrint = new XMLOutputter(Format.getPrettyFormat());
		this.parent = parent;
		jFc.setMultiSelectionEnabled(false);
		preferencesLoaded = false;
		jFc.setFileSelectionMode(JFileChooser.FILES_ONLY);
		jFc.setDialogType(JFileChooser.OPEN_DIALOG);
		bc = new basicCrypto();
	}
	
	/**
	 * Writes all runing global parameters to a config file in xml format
	 * Note that there is room for improvement using a single JDOM Document in the MainWindow class core to hold
	 * all the parameters other than using a single variable for each parameter
	 * 
	 * @param ipa	IP Address or Hostname of the SRX Device
	 * @param aus	JUNOS username with rights to change access stanzas
	 * @param apw	JUNOS username's password
	 * @param rnet	Dynamic VPN remote network (x.x.x./x)
	 * @param lip	DynamiC VPN low IP address in range
	 * @param hip	Dynamic VPN high IP address in range
	 * @param dip	Dynamic VPN DNS server address
	 * @throws IOException	The calling method may need to know if we're unable to write the config file
	 */
	public void setParams (String ipa, String aus, String apw, String rnet, String lip, String hip, String dip) throws IOException {
		PrintWriter outputStream = null;
		outputStream = new PrintWriter(new FileWriter(prefFile));
		ipAddress = ipa;
		adminUsername = aus;
		adminPassword = apw;
		remoteNetwork = rnet;
		lowIp = lip;
		highIp = hip;
		dnsIp = dip;
		root.getChild("ipAddress").setText(ipAddress);
		root.getChild("adminUsername").setText(adminUsername);
		root.getChild("adminPassowrd").setText(bc.getCryptoPassword(adminPassword));
		root.getChild("remoteNetwork").setText(remoteNetwork);
		root.getChild("lowIp").setText(lowIp);
		root.getChild("highIp").setText(highIp);
		root.getChild("dnsIp").setText(dnsIp);
		xmlPrint.output(doc, outputStream);
		outputStream.close();
	}
	
	/**
	 * Reads parameters from the config file and sets the class variables
	 * Note that there is room for improvement using a fingle JDOM Document element other than single
	 * variables for every parameter
	 * @param xsdConfig		This is the URL to the XSD schema file
	 * @throws JDOMException	Calling method must know if we're unable to parse the XML file
	 * @throws IOException		Calling method may need to know if we have any probles reading from the file
	 */
	public void getParams (URL xsdConfig) throws JDOMException, IOException{
		SAXBuilder builder = new SAXBuilder("org.apache.xerces.parsers.SAXParser", true);
		builder.setFeature("http://apache.org/xml/features/validation/schema", true);
		builder.setProperty("http://apache.org/xml/properties/schema/external-noNamespaceSchemaLocation", xsdConfig.toString());
		doc = builder.build(prefFile);
		root = doc.getRootElement();
		try {
			adminPassword = bc.getDecryptedPassword(root.getChildText("adminPassowrd"));
		} catch (Exception e) {
//			We're unable to decrypt the password in the config file. Return without parameters
			return;
		}
		ipAddress = root.getChildText("ipAddress");
		adminUsername = root.getChildText("adminUsername");
		remoteNetwork = root.getChildText("remoteNetwork");
		lowIp = root.getChildText("lowIp");
		highIp = root.getChildText("highIp");
		dnsIp = root.getChildText("dnsIp");
//		We'll set the variable to the calling method can test if we've been sucessfull reading parameters
		preferencesLoaded = true;
	}
	
	/**
	 * Saves the current user database with only crytopasswords
	 * @param usersData		The JDOM document holding the current database
	 * @throws XSLTransformException	The xsl transformation that hides the clearText password
	 * @throws IOException	The calling method may need to know we've failed to write to the file
	 */
	public void saveUsers (Document usersData) throws XSLTransformException, IOException {
		int value;
		PrintWriter outputStream = null;
		value=jFc.showOpenDialog(parent);
		usersFile = jFc.getSelectedFile();
//		If the users choses to cancel file selection dialog we simply return without writing to file
		if (value == JFileChooser.CANCEL_OPTION) return;
		outputStream = new PrintWriter(usersFile);
		xmlPrint.output(xlsPrivate.transform(usersData),outputStream);
		outputStream.close();
	}
	
	/**
	 * Gets users from XML file
	 * @param xsdUrl 	The URL to the XSD schema to use when parsing. It may be "OPEN" (cryptopasswords required)
	 * or "IMPORT" (password clear text required)
	 * @return		The user data or null if no file selected
	 * @throws IOException 	We've been unable to read from file
	 * @throws JDOMException We've been unable to parse the XML file
	 */
	
	public Document openUsers(URL xsdUrl) throws JDOMException, IOException {
		Document usersDoc = null;
		int value;
		value = jFc.showOpenDialog(parent);
		usersFile = jFc.getSelectedFile();
		if (value == JFileChooser.CANCEL_OPTION) return null;
		SAXBuilder builder = new SAXBuilder("org.apache.xerces.parsers.SAXParser", true);
		builder.setFeature("http://apache.org/xml/features/validation/schema", true);
		builder.setProperty("http://apache.org/xml/properties/schema/external-noNamespaceSchemaLocation", xsdUrl.toString());
		usersDoc = builder.build(usersFile);
		return usersDoc;
	}
}